home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 41
/
Amiga Format CD41 (1999-06)(Future Publishing)(GB)[!][issue 1999-07].iso
/
-seriously_amiga-
/
programming
/
other
/
flexcat
/
flexcat.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-04-19
|
61KB
|
2,690 lines
/*****************************************************************
** **
** If you use GoldED or any other text editor featuring folding **
** you may want to set up "///" as fold opening phrase, and **
** "//|" as closing one, as this source is using it. **
** **
** Marcin **
** **
*****************************************************************/
#define __amigados
/// README
/*
FlexCat.c: The flexible catalog creator
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Ok, this is nothing special. It grabs a catalog translation and a
catalog description file and produces catalogs and the source to
handle them. What is it else than lots of other programs?
The difference is, that YOU determine what source FlexCat produces.
Another file is scanned by FlexCat to produce code. This file contains
some c-string like special characters (%v for version for example)
You can edit this file and modify it as you want. So FlexCat can produce
C source as well as Assembler, Oberon, Modula 2, E, ...
*/
//|
#define VERSION 2
#define REVISION 2
#define VERS "FlexCat 2.2"
#ifdef _M68060
#define _CPU "[68060]"
#else
#ifdef _M68040
#define _CPU "[68040]"
#else
#ifdef _M68030
#define _CPU "[68030]"
#else
#ifdef _M68020
#define _CPU "[68020]"
#else
#ifdef _M68010
#define _CPU "[68010]"
#else
#define _CPU "[680x0]"
#endif
#endif
#endif
#endif
#endif
#define VSTRING VERS " " _CPU " " __AMIGADATE__
#define VERSTAG "$VER: " VSTRING
/// Includes and defines
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <dos.h>
#include "FlexCat_cat.h"
#if ((defined(_DCC) && defined(AMIGA)) || \
(defined(__SASC) && defined(_AMIGA))) && \
!defined(__amigados)
#define __amigados
#endif
#if defined(__amigados)
#include <exec/types.h>
#if defined(_DCC) || defined(__SASC) || defined(__GNUC__)
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/utility.h>
#else
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/utility_protos.h>
#endif
#ifdef tolower
#undef tolower
#endif
#define tolower ToLower
#define stricmp(s,t) Stricmp((STRPTR) (s), (STRPTR) (t))
#define strnicmp(s,t,l) Strnicmp((STRPTR) (s), (STRPTR) (t), l)
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE (!FALSE)
#endif
#define MAXPATHLEN 512
#define FLEXCAT_SDDIR "FLEXCAT_SDDIR"
#if defined(__amigados)
#define DEFAULT_FLEXCAT_SDDIR "PROGDIR:lib"
#else
#define DEFAULT_FLEXCAT_SDDIR "lib"
#endif
#if defined(__amigados)
#define MAX_PREFS_LEN 512
#define FLEXCAT_PREFS "flexcat.prefs"
char prefs_sddir[MAXPATHLEN] = "\0";
#endif
//|
/// Structs
enum StringTypes {
TYPE_C, /* Produce C strings */
TYPE_ASSEMBLER, /* Produce Assembler strings */
TYPE_OBERON, /* Produce Oberon strings */
TYPE_E, /* Produce E strings. (Oops, thought */
/* it allows only 32 bit integers? ;-) */
TYPE_NONE /* Simple strings */
};
enum OutputModes {
OutputMode_None, /* Nothing written yet */
OutputMode_Bin, /* Last character written was binary */
OutputMode_Ascii /* Last character written was Ascii */
};
struct CatString
{ struct CatString *Next;
char *CD_Str;
char *CT_Str;
char *ID_Str;
int MinLen, MaxLen, ID, Nr;
int NotInCT; /* If string is not present we write NEW */
/* while updating CT file, for easier work. */
};
struct CDLine
{ struct CDLine *Next;
char *Line;
};
struct CatalogChunk
{ struct CatalogChunk *Next;
ULONG ID;
char *ChunkStr;
};
struct CatString *FirstCatString = NULL; /* First catalog string */
struct CDLine *FirstCDLine = NULL; /* First catalog description line */
struct CatalogChunk *FirstChunk = NULL; /* List of catalog chunks */
char *BaseName = ""; /* Basename of catalog description */
char *Language = "english"; /* Language of catalog description */
int CatVersion = 0; /* Version of catalog to be opened */
int LengthBytes = 0; /* Number of bytes to preceed a */
/* created string and containing */
/* its length. */
char *CatLanguage = NULL; /* Language of catalog translation */
char *CatVersionString = NULL; /* version string of catalog */
/* translation (## version) */
char *CatRcsId = NULL; /* rcs ID of catalog translation */
/* (## rcsid) */
char *CatName = NULL; /* name of catalog translation */
int CodeSet = 0; /* Codeset of catalog translation */
int NumStrings = 0; /* Number of catalog strings */
int LongStrings = TRUE; /* Generate long or short strings */
char *ScanFile; /* File currently scanned */
int ScanLine; /* Line currently scanned */
int GlobalReturnCode = 0; /* Will be 5, if warnings appear */
int WarnCTGaps = FALSE; /* Warn missing symbols in CT */
/* file. */
int NoOptim = FALSE; /* Put string into catalog even */
/* if translation is equal to */
/* description. */
int Fill = FALSE; /* It translation of given string */
/* is missing or it's empty, write */
/* string descriptor from #?.cd */
/* file instead. */
int DoExpunge = FALSE; /* If TRUE FlexCat will do AVAIL */
/* FLUSH alike after catalog save */
int NoBeep = FALSE; /* if TRUE, FlexCat won't call */
/* DisplayBeep() any longer */
int Quiet = FALSE; /* Forces FlexCat to shut up */
int NumberOfWarnings = 0; /* We count warnings to be smart */
/* and not to do Beep bombing, but */
/* call DisplayBeep() only once */
int CT_Scanned = FALSE; /* If TRUE, and we are going to */
/* write new #?.ct file, then user */
/* surely updates own #?.ct file */
/* so we should write ***NEW*** */
/* whenever necessary. */
int LANGToLower = TRUE; /* Shall we do ToLower() on lang's */
/* name? Some #?.language seems to */
/* be broken, so we allow workaround */
int NoBufferedIO = FALSE; /* Shall we do buffered IO */
int buffer_size = 2048; /* Size of the IO buffer */
int Modified = FALSE; /* Shall we write the catalog ONLY */
/* if #?.catalog is younger than */
/* #?.c(d|t) files? */
#define MAX_NEW_STR_LEN 25
char Msg_New[MAX_NEW_STR_LEN] = "***NEW***";
/* new strings in updated #?.ct */
int CopyNEWs = FALSE;
char Old_Msg_New[MAX_NEW_STR_LEN] = "; ***NEW***";
/* old newstring (above) used in old */
/* CT file. Now we look if it's present */
/* and copy it into new CT if user does */
/* upgrade (flexcat CD CT newctfile CT */
char VersTag[] = VERSTAG;
char VString[] = VSTRING " by Jochen Wiedmann and Marcin Orlowski";
char EString[] = "E-mail: carlos@amiga.com.pl WWW: http://amiga.com.pl/flexcat/";
//|
/// FUNC: ReadPrefs
#if defined(__amigados)
char ReadPrefs(void)
{
enum{ SDDIR,
MSG_NEW,
WARNCTGAPS,
NOOPTIM,
FILL,
FLUSH,
NOBEEP,
QUIET,
NOLANGTOLOWER,
NOBUFFEREDIO,
MODIFIED,
COPYMSGNEW,
OLDMSGNEW,
ARGS_COUNT
};
char template[] = "SDDIR/K,MSG_NEW/K,WARNCTGAPS/S,NOOPTIM/S,FILL/S,FLUSH/S,NOBEEP/S,QUIET/S,NOLANGTOLOWER/S,NOBUFFEREDIO/S,MODIFIED/S,COPYMSGNEW/S,OLDMSGNEW/K";
LONG Results[ARGS_COUNT] = {0};
char result = FALSE;
char *prefs;
struct RDArgs *rda;
struct RDArgs *rdargs;
if(prefs = getenv(FLEXCAT_PREFS))
{
prefs = realloc(prefs, strlen(prefs)+1);
strcat(prefs, "\n");
if(rda = AllocDosObject(DOS_RDARGS, TAG_DONE))
{
rda->RDA_Source.CS_Buffer = prefs;
rda->RDA_Source.CS_Length = strlen(prefs);
rda->RDA_Source.CS_CurChr = 0;
rda->RDA_Flags |= RDAF_NOPROMPT;
if(rdargs = ReadArgs(template, Results, rda))
{
if(Results[SDDIR])
strncpy(prefs_sddir, (char *)Results[SDDIR], MAXPATHLEN);
if(Results[MSG_NEW])
strncpy(Msg_New, (char *)Results[MSG_NEW], MAX_NEW_STR_LEN);
WarnCTGaps = Results[WARNCTGAPS];
NoOptim = Results[NOOPTIM];
Fill = Results[FILL];
DoExpunge = Results[FLUSH];
NoBeep = Results[NOBEEP];
Quiet = Results[QUIET];
LANGToLower = Results[NOLANGTOLOWER];
Modified = Results[MODIFIED];
NoBufferedIO = Results[NOBUFFEREDIO];
CopyNEWs = Results[COPYMSGNEW];
if(Results[OLDMSGNEW])
sprintf(Old_Msg_New, "; %s", (char *)Results[OLDMSGNEW]);
FreeArgs(rdargs);
result = TRUE;
}
else
{
fputs((char *)msgPrefsError, stderr);
fputs((char *)template, stderr);
fputs((char *)"\n", stderr);
DisplayBeep(NULL);
}
FreeDosObject(DOS_RDARGS, rda);
}
else
{
fputs("Error processing prefs.\nCan't AllocDosObject()\n", stderr);
}
free(prefs);
}
return(result);
}
#endif
//|
/// FUNC: MyExit
void MyExit (int Code)
{
#if defined(__amigados)
if(((NumberOfWarnings > 0) ||(Code !=0)) && (!NoBeep))
DisplayBeep(NULL);
#endif
exit(Code);
}
//|
/// FUNC: ShowError
/*
This shows an error message and terminates
*/
struct RDArgs *Args;
void ShowError(const UBYTE (*msg), ...)
{ char **ptr = (char **) &msg;
// if(!Quiet)
{
fprintf(stderr, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4]);
putc('\n', stderr);
}
#if defined(__amigados)
NumberOfWarnings++;
#endif
MyExit(10);
}
//|
/// FUNC: MemError
/*
This shows the message: Memory error.
*/
void MemError(void)
{
ShowError(msgMemoryError, NULL);
}
//|
/// FUNC: ShowWarn
/*
This shows a warning
*/
void ShowWarn(const UBYTE (*msg), ...)
{ char **ptr = (char **) &msg;
if(!Quiet)
{
fprintf(stderr, (char *) msgWarning, ScanFile, ScanLine);
fprintf(stderr, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4]);
putc('\n', stderr);
}
NumberOfWarnings++;
GlobalReturnCode = 5;
}
//|
/// FUNC: AllocString
/*
This allocates a string
*/
char *AllocString(const char *str)
{ char *ptr;
if (!(ptr = malloc(strlen(str)+1)))
{ MemError();
}
strcpy(ptr, str);
return(ptr);
}
//|
/// FUNC: Add catalog chunk
/*
This adds a new catalog chunk to the list of catalog
chunks.
*/
char *AddCatalogChunk(char *ID, const char *string)
{
struct CatalogChunk *cc, **ccptr;
if (!(cc = malloc(sizeof(*cc))))
{ MemError();
}
cc->Next = NULL;
cc->ID = *((ULONG *) ID);
cc->ChunkStr = AllocString(string);
/*
Put the new chunk to the end of the chunk list.
*/
for (ccptr = &FirstChunk; *ccptr != NULL; ccptr = &(*ccptr)->Next)
{
}
*ccptr = cc;
return(cc->ChunkStr);
}
//|
/// FUNC: gethex
/*
This translates a hex character.
*/
int gethex(int c)
{
if (c >= '0' && c <= '9')
{ return(c - '0');
}
else if (c >= 'a' && c <= 'f')
{ return(c - 'a' + 10);
}
else if (c >= 'A' && c <= 'F')
{ return(c - 'A' + 10);
}
ShowWarn(msgExpectedHex);
return(0);
}
//|
/// FUNC: getoctal
/*
This translates an octal digit.
*/
int getoctal(int c)
{
if (c >= '0' && c <= '7')
{
return(c - '0');
}
ShowWarn(msgExpectedOctal);
return(0);
}
//|
/// FUNC: ReadLine
/*
Reading a line is somewhat complicated in order to allow lines of any
length.
Inputs: fp - the file, where the input comes from
AllowComment - TRUE, if a leading semicolon should force to
interpret the line as a comment line
*/
#define BUFSIZE 4096
char *ReadLine(FILE *fp, int AllowComment)
{
char *OldLine, *NewLine = NULL;
int c = '\0';
int Len = 0, LineLen = 0;
int FirstChar = TRUE;
int BackslashSeen = FALSE;
int BackslashSeenOn = 0; /* position the last backslash was seen on */
int CommentLine = FALSE; /* if TRUE we should ignore normally treat trailing \'s */
while(c != EOF)
{
if(Len+10 > LineLen)
{
OldLine = NewLine;
if(!(NewLine = malloc(LineLen+BUFSIZE)))
MemError();
strncpy(NewLine, OldLine, LineLen);
if(OldLine)
free(OldLine);
LineLen += BUFSIZE;
}
c = getc(fp);
if(FirstChar)
{
if(c == EOF)
{
free(NewLine);
return(NULL);
}
if(c == ';')
{
CommentLine = TRUE;
}
FirstChar = FALSE;
}
switch(c)
{
case '\r':
break;
case '\n':
++ScanLine;
if(BackslashSeen)
{
NewLine[Len++] = c;
BackslashSeen = FALSE;
break;
}
c = EOF;
case EOF:
break;
/* Let's check for trailing \\ */
case '\\':
{
if(!CommentLine)
{
if(BackslashSeen)
{
if(BackslashSeenOn == (Len-1))
{
BackslashSeen = FALSE;
NewLine[Len++] = c;
break;
}
}
BackslashSeen = TRUE;
BackslashSeenOn = Len;
}
NewLine[Len++] = c;
break;
}
default:
BackslashSeen = FALSE;
NewLine[Len++] = c;
}
}
NewLine[Len] = '\0';
return(NewLine);
}
//|
/// FUNC: OverSpace
/*
This removes trailing blanks.
*/
void OverSpace(char **strptr)
{ int c;
while ((c = **strptr) == ' ' || c == '\t')
{ (*strptr)++;
}
}
//|
/// FUNC: Expunge
void Expunge(void)
{
#if defined(__amigados)
if(DoExpunge)
{
#ifdef __EXPUNGE_ALL__
APTR Memory;
if(Memory = AllocMem(-1, NULL))
FreeMem(Memory, -1); // just in case ;-)
#else
#pragma libcall LocaleBase localeExpunge 12 00
VOID localeExpunge(VOID);
struct Library *LocaleBase;
if(LocaleBase = OpenLibrary("locale.library", 0))
{
localeExpunge();
CloseLibrary(LocaleBase);
}
#endif
}
#endif
}
//|
/// FUNC: ReadChar
/*
ReadChar scans an input line translating the backslash characters.
Inputs: strptr - a pointer to a stringpointer; the latter points to the
next character to be read and points behind the read
bytes after executing ReadChar
dest - a pointer to a buffer, where the read bytes should be
stored
Result: number of bytes that are written to dest (between 0 and 2)
*/
int ReadChar(char **strptr, char *dest)
{
char c;
int i;
switch(c = *((*strptr)++))
{
case '\\':
switch(c = tolower((int) *((*strptr)++)))
{
case '\n':
return(0);
case 'b':
*dest = '\b';
break;
case 'c':
*dest = '\233';
break;
case 'e':
*dest = '\033';
break;
case 'f':
*dest = '\f';
break;
case 'g':
*dest = '\007';
break;
case 'n':
*dest = '\n';
break;
case 'r':
*dest = '\r';
break;
case 't':
*dest = '\t';
break;
case 'v':
*dest = '\013';
break;
case 'x':
*dest = gethex((int) **strptr);
(*strptr)++;
if (((c = **strptr) >= '0' && c <= '9') ||
(c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
{ *dest = (*dest << 4) + gethex((int) c);
(*strptr)++;
}
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
*dest = getoctal((int)c);
for(i = 0; i < 2; i++)
{
if((c = **strptr) >= '0' && c <= '7')
{
*dest = (*dest << 3) + getoctal((int) c);
(*strptr)++;
}
}
break;
case ')':
case '\\':
*(dest++) = '\\';
*dest = c;
return(2);
default:
*dest = c;
}
break;
default:
*dest = c;
}
return(1);
}
//|
/// FUNC: ScanCDFile
/*
This scans the catalog description file.
Inputs: cdfile - name of the catalog description file
Result: TRUE, if successful, FALSE otherwise
*/
int ScanCDFile(char *cdfile)
{
FILE *fp;
struct CDLine *cdline, **cdptr = &FirstCDLine;
struct CatString *cs, **csptr = &FirstCatString;
char *line, *newline;
char *ptr;
int NextID = 0, len;
int Result = TRUE;
ScanFile = cdfile;
ScanLine = 0;
if(!(fp = fopen(cdfile, "r")))
{
ShowError(msgNoCatalogDescription, cdfile);
}
if(!NoBufferedIO)
setvbuf(fp, NULL, _IOFBF, buffer_size);
/*
Get the basename
*/
if ((ptr = strchr(cdfile, ':')))
{ cdfile = ptr+1;
}
if ((ptr = strrchr(cdfile, '/')))
{ cdfile = ptr+1;
}
if ((ptr = strrchr(cdfile, '.')))
{ len = ptr-cdfile;
}
else
{ len = strlen(cdfile);
}
if (!(BaseName = malloc(len+1)))
{ MemError();
}
strncpy(BaseName, cdfile, len);
BaseName[len] = '\0';
while(!feof(fp) && (line = newline = ReadLine(fp, TRUE)))
{
if(!(cdline = malloc(sizeof(*cdline))))
{
MemError();
}
*cdptr = cdline;
cdptr = &cdline->Next;
cdline->Next = NULL;
cdline->Line = line = AllocString(newline);
free(newline);
if (*line == ';')
{
continue;
}
if(*line == '#')
{
int CheckExtra = TRUE;
if (strnicmp(line+1, "language", 8) == 0)
{
char *ptr;
line += 9;
OverSpace(&line);
Language = AllocString(line);
if(LANGToLower)
{
for (ptr = Language; *ptr; ptr++)
{
*ptr = tolower((int) *ptr);
}
CheckExtra = FALSE;
}
}
else
if(strnicmp(line+1, "version", 7) == 0)
{
CatVersion = strtol(line+8, &line, 0);
}
else
{
if(strnicmp(line+1, "basename", 8) == 0)
{
line += 9;
OverSpace(&line);
free(BaseName);
BaseName = AllocString(line);
CheckExtra = FALSE;
}
else
{
ShowWarn(msgUnknownCDCommand);
Result = FALSE;
CheckExtra = FALSE;
}
}
if(CheckExtra)
{
OverSpace(&line);
if(*line)
{
ShowWarn(msgExtraCharacters);
Result = FALSE;
}
}
}
else
{
char *idstr;
if(*line == ' ' || *line == '\t')
{
ShowWarn(msgUnexpectedBlanks);
Result = FALSE;
OverSpace(&line);
}
idstr = line;
while ((*line >= 'a' && *line <= 'z') ||
(*line >= 'A' && *line <= 'Z') ||
(*line >= '0' && *line <= '9') ||
*line == '_')
{
++line;
}
if(idstr == line)
{
ShowWarn(msgNoIdentifier);
Result = FALSE;
}
else
{
int found;
if(!(cs = malloc(sizeof(*cs))))
{
MemError();
}
do
{
struct CatString *scs;
found = TRUE;
for(scs = FirstCatString; scs != NULL; scs = scs->Next)
{
if(scs->ID == NextID)
{
found = FALSE;
++NextID;
break;
}
}
}
while(!found);
cs->Next = NULL;
cs->ID = NextID;
cs->MinLen = 0;
cs->MaxLen = -1;
cs->CD_Str = "";
cs->CT_Str = NULL;
cs->NotInCT= TRUE;
if(!(cs->ID_Str = malloc((line-idstr)+1)))
{
MemError();
}
strncpy(cs->ID_Str, idstr, line-idstr);
cs->ID_Str[line-idstr] = '\0';
OverSpace(&line);
if(*line != '(')
{
ShowWarn(msgNoLeadingBracket);
Result = FALSE;
}
else
{
char *oldstr;
struct CatString *scs;
char bytes[10];
int bytesread, reallen;
++line;
OverSpace(&line);
if(*line != '/')
{
if(*line == '+')
{
NextID = cs->ID = NextID + strtol(line, &line, 0);
}
else
{
cs->ID = NextID = strtol(line, &line, 0);
}
OverSpace(&line);
}
for(scs = FirstCatString; scs != NULL; scs = scs->Next)
{ if (scs->ID == cs->ID)
{ ShowWarn(msgDoubleID);
Result = FALSE;
}
if (strcmp(cs->ID_Str, scs->ID_Str) == 0)
{ ShowWarn(msgDoubleIdentifier);
Result = FALSE;
}
}
if (*line != '/')
{ ShowWarn(msgNoMinLen);
Result = FALSE;
}
else
{ ++line;
OverSpace(&line);
if (*line != '/')
{ cs->MinLen = strtol(line, &line, 0);
OverSpace(&line);
}
if (*line != '/')
{ ShowWarn(msgNoMaxLen);
Result = FALSE;
}
else
{ ++line;
OverSpace(&line);
if (*line != ')')
{ cs->MaxLen = strtol(line, &line, 0);
OverSpace(&line);
}
if (*line != ')')
{ ShowWarn(msgNoTrailingBracket);
Result = FALSE;
}
else
{ ++line;
OverSpace(&line);
if (*line)
{ ShowWarn(msgExtraCharacters);
}
}
}
}
if (!(newline = ReadLine(fp, FALSE)))
{ ShowWarn(msgNoString);
Result = FALSE;
cs->CD_Str = "";
}
else
{ cs->CD_Str = AllocString(newline);
free(newline);
}
/*
Get stringlen
*/
oldstr = cs->CD_Str;
reallen = 0;
while (*oldstr)
{ bytesread = ReadChar(&oldstr, bytes);
if (bytesread == 2)
{ bytesread--;
}
reallen += bytesread;
}
if (cs->MinLen > 0 && reallen < cs->MinLen)
{ ShowWarn(msgShortString);
}
if (cs->MaxLen > 0 && reallen > cs->MaxLen)
{ ShowWarn(msgLongString);
}
cs->Nr = NumStrings;
*csptr = cs;
csptr = &cs->Next;
++NumStrings;
}
}
}
}
fclose(fp);
return(Result);
}
//|
/// FUNC: ScanCTFile
/*
This scans a catalog translation file.
Inputs: ctfile - name of the translation file to scan.
Result: TRUE, if successful, FALSE otherwise.
*/
int ScanCTFile(char *ctfile)
{
FILE *fp;
char *newline, *line, *idstr, *newidstr, *newstr;
struct CatString *cs=NULL;
int Result = TRUE;
ScanFile = ctfile;
ScanLine = 0;
if (!(fp = fopen(ctfile, "r")))
{
ShowError(msgNoCatalogTranslation, ctfile);
}
if(!NoBufferedIO)
setvbuf(fp, NULL, _IOFBF, buffer_size);
while (!feof(fp) && (line = newline = ReadLine(fp, TRUE)))
{
switch(*line)
{
case ';':
if( CopyNEWs == TRUE )
{
if(strnicmp( line, Old_Msg_New, strlen(Old_Msg_New) ) == 0)
{
cs->NotInCT = TRUE;
}
}
break;
case '#':
/// looking for command;
if(*(++line) != '#')
{
ShowWarn(msgNoCTCommand);
}
++line;
OverSpace(&line);
if (strnicmp(line, "version", 7) == 0)
{ if (CatVersionString || CatRcsId || CatName)
{ ShowWarn(msgDoubleCTVersion);
}
line += 7;
OverSpace(&line);
CatVersionString = AllocString(line);
}
else if (strnicmp(line, "codeset", 7) == 0)
{ line += 7;
CodeSet = strtol(line, &line, 0);
OverSpace(&line);
if (*line)
{ ShowWarn(msgExtraCharacters);
}
}
else if (strnicmp(line, "language", 8) == 0)
{ char *ptr;
if (CatLanguage)
{ ShowWarn(msgDoubleCTLanguage);
}
line += 8;
OverSpace(&line);
CatLanguage = AddCatalogChunk("LANG", line);
if(LANGToLower)
for (ptr = CatLanguage; *ptr; ptr++)
*ptr = tolower((int) *ptr);
}
else if (strnicmp(line, "chunk", 5) == 0)
{ char *ID;
line += 5;
OverSpace(&line);
ID = line;
line += sizeof(ULONG);
OverSpace(&line);
AddCatalogChunk(ID, AllocString(line));
}
else if (strnicmp(line, "rcsid", 5) == 0)
{ if (CatVersionString || CatRcsId)
{ ShowWarn(msgDoubleCTVersion);
}
line += 5;
OverSpace(&line);
CatRcsId = AllocString(line);
}
else if (strnicmp(line, "name", 5) == 0)
{ if (CatVersionString || CatName)
{ ShowWarn(msgDoubleCTVersion);
}
line += 4;
OverSpace(&line);
CatName = AllocString(line);
}
else if (strnicmp(line+1, "lengthbytes", 11) == 0)
{ line += 12;
if ((LengthBytes = strtol(line, &line, 0))
> sizeof(long))
{ ShowWarn(msgNoLengthBytes, sizeof(long));
LengthBytes = sizeof(long);
}
}
else
{
ShowWarn(msgUnknownCTCommand);
}
//|
break;
default:
if(*line == ' ' || *line == '\t')
{
ShowWarn( msgUnexpectedBlanks );
OverSpace( &line );
}
idstr = line;
while ((*line >= 'a' && *line <= 'z') ||
(*line >= 'A' && *line <= 'Z') ||
(*line >= '0' && *line <= '9') ||
*line == '_')
{ ++line;
}
if (idstr == line)
{
ShowWarn(msgNoIdentifier);
break;
}
if(!(newidstr = malloc(line-idstr+1)))
{
MemError();
}
strncpy(newidstr, idstr, line-idstr);
newidstr[line-idstr] = '\0';
OverSpace(&line);
if(*line)
{
ShowWarn(msgExtraCharacters);
}
if((newstr = ReadLine(fp, FALSE)))
{
for(cs = FirstCatString; cs != NULL; cs = cs->Next)
{
if(strcmp(cs->ID_Str, newidstr) == 0)
{
break;
}
}
if(cs == NULL)
{
ShowWarn(msgUnknownIdentifier, newidstr);
}
else
{
char *oldstr;
char bytes[10];
int bytesread, reallen;
if(cs->CT_Str)
{
ShowWarn(msgDoubleIdentifier);
Result = FALSE;
free(cs->CT_Str);
}
cs->CT_Str = AllocString(newstr);
cs->NotInCT = FALSE;
/*
Get stringlen
*/
oldstr = cs->CT_Str;
reallen = 0;
while(*oldstr)
{
bytesread = ReadChar(&oldstr, bytes);
if(bytesread == 2)
{
bytesread--;
}
reallen += bytesread;
}
if(cs->MinLen > 0 && reallen < cs->MinLen)
{
ShowWarn(msgShortString);
}
if(cs->MaxLen > 0 && reallen > cs->MaxLen)
{
ShowWarn(msgLongString);
}
// checking for trailing ellipsis...
if( reallen >= 3 )
{
long cd_len = strlen( cs->CD_Str );
if( cd_len >= 3 )
{
if( strcmp( &cs->CD_Str[ cd_len - 3 ], "..." ) == 0 )
if( strcmp( &cs->CT_Str[ reallen - 3 ], "..." ) != 0 )
ShowWarn(msgTrailingEllipsis);
}
}
// checking for trailing spaces
if( reallen >= 1 )
{
long cd_len = strlen( cs->CD_Str );
if( cd_len >= 1 )
{
if( strcmp( &cs->CD_Str[ cd_len - 1 ], " " ) == 0 )
if( strcmp( &cs->CT_Str[ reallen - 1 ], " " ) != 0 )
ShowWarn(msgTrailingSpaces);
}
}
}
free(newstr);
}
else
{
ShowWarn(msgNoString);
if(cs)
cs->CT_Str = "";
}
free(newidstr);
}
free(newline);
}
fclose(fp);
if (WarnCTGaps)
{ for (cs = FirstCatString; cs != NULL; cs = cs->Next)
{ if (cs->CT_Str == NULL)
{ ShowWarn(msgCTGap, cs->ID_Str);
}
}
}
if(Result)
CT_Scanned = TRUE;
return(Result);
}
//|
/// FUNC: CatPuts
/*
CatPuts prints a string to a catalog. (The string is preceded by a
long integer containing its length and probably padded up to word
boundary or longword boundary, depending on the argument padbytes.)
The arguments countnul should be TRUE if the NUL byte at the end of
the string should be counted.
*/
int CatPuts(FILE *fp, char *str, int padbytes, int countnul)
{
unsigned long reallen, virtuallen, chunklen;
int bytesread;
char *oldstr;
char bytes[10];
/* Get Length of string.
*/
oldstr = str;
reallen = 0;
while(*oldstr)
{
bytesread = ReadChar(&oldstr, bytes);
if(bytesread == 2)
{
bytesread--;
}
reallen += bytesread;
}
virtuallen = chunklen = reallen + LengthBytes;
if(countnul || chunklen % padbytes == 0)
{
virtuallen++;
}
fwrite(&virtuallen, sizeof(virtuallen), 1, fp);
if(LengthBytes)
{
fwrite(((char *) &reallen)+sizeof(reallen)-LengthBytes, LengthBytes, 1, fp);
}
while(*str)
{
bytesread = ReadChar(&str, bytes);
if(bytesread)
{
fwrite(bytes+bytesread-1, 1, 1, fp);
}
}
do
{
putc('\0', fp);
}
while(++chunklen % padbytes);
return((int) chunklen+4);
}
//|
/// FUNC: PutCatalogChunk
/*
This puts a string chunk into the catalog
*/
int PutCatalogChunk(FILE *fp, struct CatalogChunk *cc)
{
fwrite(&cc->ID, sizeof(cc->ID), 1, fp);
return(4 + CatPuts(fp, cc->ChunkStr, 2, TRUE));
}
//|
/// FUNC: CalcRealLength
/*
This function measures the real (binary) length of source
string. It correctly process 'slash chars' (\n, \000 etc),
and gives the real length such source string have.
Inputs: source - pointer to null terminated source string
Result: real length
*/
int CalcRealLength(char *source)
{
int count = 0;
char *src = source;
char bytes[10];
while(*src)
{
count += ReadChar(&src, bytes);
}
// printf("%ld: '%s'\n", count, source);
return(count);
}
//|
/// FUNC: CreateCatalog
/*
This creates a catalog.
*/
void CreateCat(char *CatFile)
{
FILE *fp;
int CatLen, HeadLen;
struct CatString *cs;
struct CatalogChunk *cc;
int i;
if(!CatVersionString && !CatRcsId)
{
ShowError(msgNoCTVersion);
}
if(!CatLanguage)
{
ShowError(msgNoCTLanguage);
}
if(strlen(CatLanguage) == 0)
{
ShowError(msgNoCTLanguage);
}
if(!(fp = fopen(CatFile, "w")))
{
ShowError(msgNoCatalog, CatFile);
}
if(!NoBufferedIO)
setvbuf(fp, NULL, _IOFBF, buffer_size);
fputs("FORM0000CTLG", fp);
CatLen = 4;
if(CatVersionString)
{
struct CatalogChunk cc;
cc.ID = 'FVER';
if(strstr(CatVersionString, "$TODAY"))
{
char *verStr;
if(verStr = malloc(strlen(CatVersionString)+128))
{
char *found = strstr(CatVersionString, "$TODAY");
char dateStr[10];
long tim;
struct tm *t;
time(&tim);
t = gmtime(&tim);
*found = 0;
strftime(dateStr, sizeof(dateStr), "%d.%m.%y", t);
sprintf(verStr, "%s%s%s", CatVersionString, dateStr, found+strlen("$TODAY"));
cc.ChunkStr = verStr;
free(verStr);
}
else
MemError();
}
else
{
cc.ChunkStr = CatVersionString;
}
CatLen += PutCatalogChunk(fp, &cc);
}
else
{
struct CatalogChunk cc;
char* verStr;
int year = 0, month = 0, day = 0;
int version = 0, revision = 0;
char* name = NULL;
char* ptr;
if(!CatRcsId)
{
ShowError(msgNoCTVersion);
}
else
{
if(!(ptr = strstr(CatRcsId, "$Date:"))
|| sscanf(ptr+6, " %d/%d/%d", &year, &month, &day) != 3
|| !(ptr = strstr(CatRcsId, "$Revision:"))
|| sscanf(ptr+10, " %d.%d", &version, &revision) != 2)
{
ShowError(msgWrongRcsId);
}
if ((ptr = strstr(CatRcsId, "$Id:")))
{ int len = 0;
char* found;
ptr += 4;
OverSpace(&ptr);
found = ptr;
while(*ptr && *ptr != '$' && *ptr != ' ' && *ptr != '\t')
{
++len;
++ptr;
}
if(!(name = malloc(len+1)))
{
MemError();
}
strncpy(name, found, len);
name[len] = '\0';
}
}
if (CatName)
{ name = CatName;
}
else if (!name)
{
ShowError(msgNoCTVersion);
name = "";
}
if (!(verStr = malloc(strlen(name) + 256)))
{
MemError();
}
sprintf(verStr, "$V");
sprintf(verStr, "ER: %s %d.%d (%d.%d.%d)", name, version, revision, day, month, year);
cc.ID = 'FVER';
cc.ChunkStr = verStr;
CatLen += PutCatalogChunk(fp, &cc);
}
for (cc = FirstChunk; cc != NULL; cc = cc->Next)
{ CatLen += PutCatalogChunk(fp, cc);
}
i = 32;
fputs("CSET", fp);
fwrite(&i, sizeof(i), 1, fp);
while(i-- > 0)
{ putc('\0', fp);
}
CatLen += 48;
fprintf(fp, "STRS0000");
HeadLen = CatLen;
for(cs = FirstCatString; cs != NULL; cs = cs->Next)
{
int FillUsed = FALSE;
if(Fill)
{
if(cs->CT_Str)
{
if(strlen(cs->CT_Str) == 0)
{
fwrite(&cs->ID, sizeof(cs->ID), 1, fp);
CatLen += 4 + CatPuts(fp, cs->CD_Str, 4, FALSE);
FillUsed = TRUE;
}
}
else
{
fwrite(&cs->ID, sizeof(cs->ID), 1, fp);
CatLen += 4 + CatPuts(fp, cs->CD_Str, 4, FALSE);
FillUsed = TRUE;
}
}
if((!FillUsed) && cs->CT_Str && (NoOptim ? TRUE : strcmp(cs->CT_Str, cs->CD_Str)))
{
fwrite(&cs->ID, sizeof(cs->ID), 1, fp);
CatLen += 4 + CatPuts(fp, cs->CT_Str, 4, FALSE);
}
}
fseek(fp, 4, SEEK_SET);
fwrite(&CatLen, sizeof(CatLen), 1, fp);
fseek(fp, HeadLen-4, SEEK_CUR);
CatLen -= HeadLen;
fwrite(&CatLen, sizeof(CatLen), 1, fp);
fclose(fp);
Expunge();
}
//|
/// FUNC: CreateCTFile
/*
This creates a new catalog translation file.
*/
void CreateCTFile(char *NewCTFile)
{
FILE *fp;
struct CDLine *cd;
struct CatString *cs;
struct CatalogChunk *cc;
char *line;
if(!CatVersionString && !CatRcsId)
{
ScanLine = 1;
ShowWarn(msgNoCTVersion);
}
if(!(fp = fopen(NewCTFile, "w")))
{
ShowError(msgNoNewCTFile);
}
if(!NoBufferedIO)
setvbuf(fp, NULL, _IOFBF, buffer_size);
if(CatRcsId)
{
fprintf(fp, "## rcsid %s\n",
CatRcsId ? CatRcsId : "");
if(CatName)
fprintf(fp, "## name %s\n", CatName);
}
else
{
if(CatVersionString)
fprintf(fp, "## version %s\n", CatVersionString);
else
{
fprintf(fp, "## version $V");
fprintf(fp, "%c", 50+19); // E
fprintf(fp, "R: XX.catalog XX.XX ($TODAY)\n");
}
}
{
char *lang = NULL;
if(CatLanguage == NULL)
if(lang = getenv("ENV:language"))
{
int i;
for(i=0;i<strlen(lang); i++)
if(lang[i] == '\n')
{
lang[i] = 0;
break;
}
CatLanguage = lang;
}
fprintf(fp, "## language %s\n## codeset %d\n;\n",
CatLanguage ? CatLanguage : "X", CodeSet);
if(lang)
{
free(lang);
CatLanguage = NULL;
}
}
for (cc = FirstChunk; cc != NULL; cc = cc->Next)
{
if (cc->ChunkStr != CatLanguage)
{
fprintf(fp, "## chunk ");
fwrite((char *) &cc->ID, sizeof(cc->ID), 1, fp);
fprintf(fp, " %s\n", cc->ChunkStr);
}
}
for(cd = FirstCDLine, cs = FirstCatString;
cd != NULL;
cd = cd->Next)
{
switch(*cd->Line)
{
case '#':
break;
case ';':
fprintf(fp, "%s\n", cd->Line);
break;
default:
if(cs)
{
/*
fprintf(fp, "%s\n", cs->ID_Str);
fprintf(fp, "%s\n", cs->CT_Str ? cs->CT_Str : "");
putc(';', fp);
putc(' ', fp);
*/
fprintf(fp, "%s\n%s\n; ", cs->ID_Str, cs->CT_Str ? cs->CT_Str : "");
for (line = cs->CD_Str; *line; ++line)
{
putc((int) *line, fp);
if(*line == '\n')
{
putc(';', fp);
putc(' ', fp);
}
}
putc('\n', fp);
if(cs->NotInCT && CT_Scanned)
fprintf(fp, ";\n; %s\n", Msg_New);
cs = cs->Next;
}
}
}
fclose(fp);
}
//|
/// FUNC: InitCatStringOutput
/*
InitCatStringOutput gets called before writing a catalog string as
source.
Inputs: fp = file pointer to the output file
type = one of TYPE_C create C strings
TYPE_ASSEMBLER create Assembler strings
TYPE_OBERON create Oberon strings
TYPE_E create E strings
TYPE_NONE create simple strings
*/
int OutputMode = OutputMode_None;
int OutputType = TYPE_C;
FILE *OutputFile;
int OutputLen;
void InitCatStringOutput(FILE *fp)
{
OutputLen = 0;
OutputFile = fp;
OutputMode = OutputMode_None;
switch(OutputType)
{ case TYPE_C:
case TYPE_OBERON:
putc('\"', fp);
OutputMode = OutputMode_Ascii;
break;
case TYPE_E:
putc('\'', fp);
case TYPE_ASSEMBLER:
case TYPE_NONE:
break;
}
}
//|
/// FUNC: SeparateCatStringOutput
/*
SeparateCatStringOutput gets called to split a catalog into separate
lines.
*/
void SeparateCatStringOutput(void)
{
switch(OutputType)
{ case TYPE_C:
if (!LongStrings)
{ fputs("\"\\\n\t\"", OutputFile);
}
break;
case TYPE_E:
if (!LongStrings)
{ fputs("\' +\n\t\'", OutputFile);
}
break;
case TYPE_OBERON:
if (!LongStrings)
{ fputs("\"\n\t\"", OutputFile);
}
break;
case TYPE_ASSEMBLER:
if (!LongStrings)
{ if (OutputMode == OutputMode_Ascii)
{ putc('\'', OutputFile);
}
putc('\n', OutputFile);
OutputMode = OutputMode_None;
}
break;
case TYPE_NONE:
break;
}
}
//|
/// FUNC: WriteBinChar
/*
WriteBinChar writes one binary character into the source file
*/
void WriteBinChar(int c)
{
switch(OutputType)
{ case TYPE_C:
case TYPE_E:
case TYPE_OBERON:
switch(c)
{ case '\b':
fputs("\\b", OutputFile);
break;
case '\n':
fputs("\\n", OutputFile);
break;
case '\r':
fputs("\\r", OutputFile);
break;
case '\t':
fputs("\\t", OutputFile);
break;
case '\f':
fputs("\\f", OutputFile);
break;
case '\0':
fputs("\\000", OutputFile);
break;
default:
if(OutputType == TYPE_E && c == '\033')
{
fputs("\\e", OutputFile);
}
else
{
fprintf(OutputFile, "\\%c%c%c", ((c >> 6) & 3) + '0',
((c >> 3) & 7) + '0', (c & 7) + '0');
}
break;
}
++OutputLen;
OutputMode = OutputMode_Bin;
break;
case TYPE_ASSEMBLER:
switch(OutputMode)
{ case OutputMode_None:
fprintf(OutputFile, "\tdc.b\t$%02x", c & 0xff);
break;
case OutputMode_Ascii:
putc('\'', OutputFile);
case OutputMode_Bin:
fprintf(OutputFile, ",$%02x", c & 0xff);
break;
}
++OutputLen;
OutputMode = OutputMode_Bin;
break;
case TYPE_NONE:
ShowWarn(msgNoBinChars);
break;
}
}
//|
/// FUNC: WriteAsciiChar
/*
WriteAsciiChar writes one ascii character into the source file.
*/
void WriteAsciiChar(int c)
{
switch(OutputType)
{ case TYPE_C:
case TYPE_OBERON:
switch(c)
{ case '\"':
fputs("\\\"", OutputFile);
break;
default:
putc(c, OutputFile);
break;
}
++OutputLen;
OutputMode = OutputMode_Ascii;
break;
case TYPE_E:
switch(c)
{ case '\'':
fputs("''", OutputFile);
break;
default:
putc(c, OutputFile);
break;
}
++OutputLen;
OutputMode = OutputMode_Ascii;
break;
case TYPE_ASSEMBLER:
if (c == '\'')
{ WriteBinChar(c);
}
else
{ switch (OutputMode)
{ case OutputMode_None:
fprintf(OutputFile, "\tdc.b\t\'%c", c);
break;
case OutputMode_Ascii:
putc(c, OutputFile);
break;
case OutputMode_Bin:
fprintf(OutputFile, ",\'%c", c);
break;
}
++OutputLen;
OutputMode = OutputMode_Ascii;
}
break;
case TYPE_NONE:
putc(c, OutputFile);
break;
}
}
//|
/// FUNC: TerminateCatStringOutput
/*
TerminateCatStringOutput finishs the output of a catalog string.
*/
void TerminateCatStringOutput(void)
{
switch(OutputType)
{ case TYPE_C:
case TYPE_OBERON:
putc('\"', OutputFile);
break;
case TYPE_E:
putc('\'', OutputFile);
break;
case TYPE_ASSEMBLER:
switch(OutputMode)
{ case OutputMode_Ascii:
putc('\'', OutputFile);
case OutputMode_Bin:
break;
case OutputMode_None:
break;
}
case TYPE_NONE:
break;
}
}
//|
/// FUNC: WriteString
/*
This writes a sourcestring.
*/
void WriteString(FILE *fpout, char *str, long Len)
{
char bytes[10];
int bytesread;
int needseparate = FALSE;
InitCatStringOutput(fpout);
if (Len >= 0)
{ int i;
for(i = LengthBytes; i >= 1; i--)
{ WriteBinChar((int) ((char *) &Len)[sizeof(Len)-i]);
}
}
while (*str)
{ bytesread = ReadChar(&str, bytes);
if (bytesread)
{ unsigned char c;
if (needseparate)
{ SeparateCatStringOutput();
needseparate = FALSE;
}
c = bytes[bytesread-1];
if ((c >= 0x20 && c < 0x7f) || c >= 0xa0)
{ WriteAsciiChar((int) c);
}
else
{ WriteBinChar((int) c);
}
}
else
{ needseparate = TRUE;
}
}
TerminateCatStringOutput();
}
//|
/// FUNC: AllocFileName
/*
This function creates a copy of a filename, removes an
optional ending and pathname components, if desired.
Inputs: filename - the filename to copy
howto - a set of bits
bit 0: 1 = remove ending, 0 = leave it
bit 1: 1 = remove pathname, 0 = leave it
Result: The copy of the filename
*/
char *AllocFileName(char *filename, int howto)
{
char *tempstr, *ptr;
if (!(tempstr = strdup(filename)))
{ MemError();
MyExit(10);
}
/* Remove pathname components, if desired */
if (howto & 2)
{ if ((ptr = strchr(tempstr, ':')))
{ tempstr = ptr+1;
}
if ((ptr = strrchr(tempstr, '/')))
{ tempstr = ptr+1;
}
}
/* Remove ending, if desired. */
if (howto & 1)
{ if ((ptr = strrchr(tempstr, '.')))
{ *ptr = '\0';
}
}
return(tempstr);
}
//|
/// FUNC: AddFileName
/*
This function adds a pathname and a filename to a full
filename.
Inputs: pathname - the leading pathname
filename - the filename
Result: The new filename
*/
char *AddFileName(char *pathname, char *filename)
{
char *buffer;
int size = strlen(pathname) + strlen(filename) + 2;
if (!(buffer = malloc(size)))
{ MemError();
MyExit(10);
}
#if defined(__amigados)
strcpy(buffer, pathname);
AddPart((STRPTR) buffer, (STRPTR) filename, size);
#else
sprintf(buffer, "%s/%s", pathname, filename);
#endif
return(buffer);
}
//|
/// FUNC: CreateSourceFile
/*
Finally the source creation.
*/
void CreateSourceFile(char *SourceFile, char *TemplateFile, char *CDFile)
{
FILE *fpin, *fpout;
char *line;
char *OrigTemplateFile = TemplateFile;
ScanFile = SourceFile;
ScanLine = 0;
/*
Open the source file. This may be found in various places
*/
if(!(fpin = fopen(TemplateFile, "r")))
{
#ifdef __amigados
if(*prefs_sddir != 0)
{
TemplateFile = AddFileName(prefs_sddir, OrigTemplateFile);
fpin = fopen(TemplateFile, "r");
}
#endif
}
if(!fpin)
{
char *sddir;
if((sddir = getenv(FLEXCAT_SDDIR)))
{
TemplateFile = AddFileName(sddir, OrigTemplateFile);
fpin = fopen(TemplateFile, "r");
}
}
if (!fpin)
{ TemplateFile = AddFileName(DEFAULT_FLEXCAT_SDDIR, OrigTemplateFile);
fpin = fopen(TemplateFile, "r");
}
if (!fpin)
{
ShowError(msgNoSourceDescription, OrigTemplateFile);
return;
}
if (!(fpout = fopen(SourceFile, "w")))
{
ShowError(msgNoSource, SourceFile);
return;
}
if(!NoBufferedIO)
setvbuf(fpin, NULL, _IOFBF, buffer_size);
if(!NoBufferedIO)
setvbuf(fpout, NULL, _IOFBF, buffer_size);
while(!feof(fpin) && (line = ReadLine(fpin, FALSE)))
{ struct CatString *cs;
int NeedRepeat;
char bytes[10];
int bytesread;
cs = FirstCatString;
do
{ char *currentline = line;
NeedRepeat = FALSE;
if (*currentline == '#' && *(++currentline) == '#')
{ ++currentline;
OverSpace(¤tline);
if (strnicmp(currentline, "stringtype", 10) == 0)
{ currentline += 10;
OverSpace(¤tline);
if (strnicmp(currentline, "c", 1) == 0)
{ OutputType = TYPE_C;
++currentline;
}
else if (strnicmp(currentline, "assembler", 9) == 0)
{ OutputType = TYPE_ASSEMBLER;
currentline += 9;
}
else if (strnicmp(currentline, "oberon", 6) == 0)
{ OutputType = TYPE_OBERON;
currentline += 6;
}
else if (strnicmp(currentline, "e", 1) == 0)
{ OutputType = TYPE_E;
++currentline;
}
else if (strnicmp(currentline, "none", 4) == 0)
{ OutputType = TYPE_NONE;
currentline += 4;
}
else
{ ShowWarn(msgUnknownStringType);
currentline += strlen(currentline);
}
OverSpace(¤tline);
if (*currentline)
{ ShowWarn(msgExtraCharacters);
}
continue;
}
else if (strnicmp(currentline, "shortstrings", 12) == 0)
{ currentline += 12;
LongStrings = FALSE;
OverSpace(¤tline);
if (*currentline)
{ ShowWarn(msgExtraCharacters);
}
continue;
}
}
currentline = line;
while(*currentline)
{ bytesread = ReadChar(¤tline, bytes);
if (bytesread)
{ if (*bytes == '%')
{ char c;
switch(c = *(currentline++))
{ case 'b':
fputs(BaseName, fpout);
break;
case 'n':
fprintf(fpout, "%d", NumStrings);
break;
case 'v':
fprintf(fpout, "%d", CatVersion);
break;
case 'l':
WriteString(fpout, Language, -1);
break;
case 'f':
{ char *tempstr;
if ((c = *currentline++) == 'v')
{ fputs(VERS, fpout);
}
else
{ tempstr = AllocFileName(CDFile, c - '0');
fputs(tempstr, fpout);
}
}
break;
case 'o':
{ char *tempstr;
tempstr = AllocFileName(SourceFile, *currentline++ - '0');
fputs(tempstr, fpout);
}
break;
case 'i':
NeedRepeat = TRUE;
if (cs) fputs(cs->ID_Str, fpout);
break;
case 'a':
case 't':
case 'd':
case 'x':
case 'c':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
int len = 0;
while(c >= '0' && c <= '9')
{
len = (c - '0') + len * 10;
c = *currentline++;
}
if(c == 'a')
{
int _len = len ? len : 4;
char *start;
char _StrLen[20 + 1];
sprintf(_StrLen, "%020lx", cs->ID);
start = &_StrLen[20-_len*2];
while(_len>0)
{
fprintf(fpout, "\\x%.2s", start);
start+=2;
_len--;
}
}
if(c == 't')
{
int _len = len ? len : 4;
char *start;
char _StrLen[20 + 1];
sprintf(_StrLen, "%020lx", ((CalcRealLength(cs->CD_Str) + 1) & 0xfffffe));
start = &_StrLen[20-_len*2];
while(_len>0)
{
fprintf(fpout, "\\x%.2s", start);
start+=2;
_len--;
}
}
if(c == 'c' || c == 'd' || c == 'x')
{
char buffer[20];
if(c == 'c') c = 'o';
if(len)
sprintf(buffer, "%%0%d%c", len, c);
else
sprintf(buffer, "%%%c", c);
if(cs) fprintf(fpout, buffer, cs->ID);
}
NeedRepeat = TRUE;
}
break;
case 'e':
NeedRepeat = TRUE;
if (cs) fprintf(fpout, "%d", cs->Nr);
break;
case 's':
NeedRepeat = TRUE;
if (cs)
{ char *idstr;
unsigned long len = 0;
if (LengthBytes)
{ idstr = cs->CD_Str;
while(*idstr)
{ bytesread = ReadChar(&idstr, bytes);
if (bytesread)
{ ++len;
}
}
}
WriteString(fpout, cs->CD_Str, LengthBytes ? len : -1);
}
break;
case '(':
NeedRepeat = TRUE;
while(*currentline && *currentline != ')')
{ bytesread = ReadChar(¤tline, bytes);
if (bytesread && cs && cs->Next)
{ putc((int) bytes[bytesread-1], fpout);
}
}
if (!*currentline)
{ ShowWarn(msgNoTerminateBracket);
}
else
{ ++currentline;
}
break;
// !!!! FIX !!!!
case 'z':
{
int diff = (((CalcRealLength(cs->CD_Str) + 1) & 0xfffffe) - (CalcRealLength(cs->CD_Str)));
NeedRepeat = TRUE;
while(diff > 0)
{
fprintf(fpout, "\\x00");
diff--;
}
break;
}
default:
{ int c = *currentline++;
putc(c, fpout);
}
}
}
else
{ putc((int) bytes[bytesread-1], fpout);
}
}
}
putc('\n', fpout);
}
while(NeedRepeat && cs && (cs = cs->Next));
free(line);
}
fclose(fpin);
fclose(fpout);
}
//|
/// FUNC: Usage
/*
The Usage function describes the programs calling syntax.
*/
void Usage(void)
{
fputs((char *) msgUsageHead, stderr);
fprintf(stderr, ": FlexCat CDFILE/A,CTFILE,CATALOG/K,NEWCTFILE/K,SOURCES/M,\n WARNCTGAPS/S,NOOPTIM/S,FILL/S,FLUSH/S,NOBEEP/S,\n QUIET/S,NOLANGTOLOWER/S,NOBUFFEREDIO/S,\n\ MODIFIED/S,COPYMSGNEW/S,OLDMSGNEW/K\n\n", VString);
fprintf(stderr, "%s\n%s%s", msgUsage, msgUsage_2, msgUsage_3);
fprintf(stderr, "\n\n%s"
/*
#ifdef _M68040
" [040]"
#else
#ifdef _M68060
" [060]"
#else
#ifdef _M68030
" [030]"
#else
#ifdef _M68020
" [020]"
#else
#ifdef _M68010
" [010]"
#endif
#endif
#endif
#endif
#endif
*/
"\n", VString);
fprintf(stderr, "%s\n", EString);
MyExit(5);
}
//|
/// FUNC: main
/*
Finally the main function. Does nothing special except for scanning
the arguments.
*/
int main (int argc, char *argv [])
{
char *cdfile, *ctfile, *newctfile, *catalog;
char *source, *template;
int i;
if(argc == 0) /* Aztec's entry point for workbench programs */
{
fprintf(stderr, "FlexCat can't be run from Workbench!\n\n");
fprintf(stderr, "Open a Shell session and type FlexCat ?\n");
fprintf(stderr, "for more information\n");
exit(5);
}
cdfile = ctfile = newctfile = catalog = NULL;
#if defined(__amigados)
ReadPrefs();
#endif
if(argc == 1)
{
Usage();
}
for (i = 1; i < argc; i++)
{
if(strnicmp (argv[i], "catalog=", 8) == 0)
{
catalog = argv[i] + 8;
}
else
if(stricmp (argv[i], "catalog") == 0)
{
if(i+1 == argc)
Usage();
catalog = argv[++i];
}
else
if(stricmp(argv[i], "nooptim") == 0)
{
NoOptim = TRUE;
}
else
if(stricmp(argv[i], "fill") == 0)
{
Fill = TRUE;
}
else
if(stricmp(argv[i], "quiet") == 0)
{
Quiet = TRUE;
}
else
if(stricmp(argv[i], "flush") == 0)
{
DoExpunge = TRUE;
}
else
if(stricmp(argv[i], "nobeep") == 0)
{
NoBeep = TRUE;
}
else
if(stricmp(argv[i], "nobufferedio") == 0)
{
NoBufferedIO = TRUE;
}
else
if (strnicmp (argv[i], "newctfile=", 10) == 0)
{
newctfile = argv[i] + 10;
}
else
if(strnicmp (argv[i], "newctfile", 10) == 0)
{
if (i+1 == argc)
Usage();
newctfile = argv[++i];
}
else
if(stricmp(argv[i], "nolangtolower") == 0)
{
LANGToLower = FALSE;
}
else
if(stricmp(argv[i], "modified") == 0)
{
Modified = TRUE;
}
else
if(stricmp(argv[i], "warnctgaps") == 0)
{
WarnCTGaps = TRUE;
}
else
if(stricmp(argv[i], "copymsgnew") == 0)
{
CopyNEWs = TRUE;
}
else
if(stricmp(argv[i], "oldmsgnew") == 0)
{
sprintf( Old_Msg_New, "; %s", argv[++i] );
}
else
if(cdfile == NULL)
{
if(stricmp(argv[i], "?") == 0 || stricmp(argv[i], "-h") == 0 || stricmp(argv[i], "help") == 0 || stricmp(argv[i], "--help") == 0)
{
Usage();
}
if(!ScanCDFile(cdfile = argv[i]))
{
MyExit(10);
}
}
else
if(strchr(argv[i], '='))
{
source = AllocString(argv[i]);
*(template = strchr(source, '=')) = '\0';
++template;
CreateSourceFile(source, template, cdfile);
}
else
{
if (ctfile)
{
Usage();
}
ctfile = argv[i];
}
}
if(Modified)
{
if(cdfile && ctfile && catalog)
{
long cd_time, ct_time, cat_time;
if((cd_time = getft(cdfile)) != -1)
{
if((ct_time = getft(ctfile)) != -1)
{
if((cat_time = getft(catalog)) == -1)
cat_time = 0;
if((cat_time > ct_time) &&
(cat_time > cd_time))
{
if(!Quiet)
{
fprintf(stderr, (char *) msgUpToDate, catalog);
putc('\n', stderr);
}
MyExit(GlobalReturnCode);
}
else
{
if(!Quiet)
{
fprintf(stderr, "--> %s", catalog);
putc('\n', stderr);
}
}
}
else
{
ShowError(msgCantCheckDate, ctfile);
}
}
else
{
ShowError(msgCantCheckDate, cdfile);
}
}
}
if(ctfile)
{
if(!ScanCTFile(ctfile))
MyExit(10);
}
if(catalog)
{
if(!ctfile)
{
fprintf(stderr, (char *) msgNoCTArgument);
Usage();
}
CreateCat(catalog);
}
if(newctfile)
{
CreateCTFile(newctfile);
}
MyExit(GlobalReturnCode);
}
//|
/// FUNC: wbmain
/*
Dice's entry point for workbench programs
*/
#if defined(__amigados) && defined(_DCC)
void wbmain(struct WBStartup *wbmsg)
{
fprintf(stderr, "FlexCat can't be run from Workbench!\n\n");
fprintf(stderr, "Open a Shell session and type FlexCat\n");
fprintf(stderr, "for syntax and more information\n");
exit(5);
}
#endif
//|